package job

import (
	"context"
	"encoding/json"
	"gcrontab/common"
	"github.com/coreos/etcd/clientv3"
	"github.com/coreos/etcd/mvcc/mvccpb"
)

//监听etcd
func (j *JobMgr) watchJobs() (err error) {
	//获取所有任务，并获取当前集群revision
	getResp, err := j.kv.Get(context.TODO(), common.JOB_SAVE_DIR, clientv3.WithPrefix())
	if err != nil {
		return
	}
	for _, val := range getResp.Kvs {
		job := &common.Job{}
		//反序列化，得到job
		if err = json.Unmarshal(val.Value, job); err == nil {
			jobEvent := common.BuildJobEvent(common.JOB_EVENT_SAVE, job)
			//推送一个添加事件给scheduler （MARK2）
			G_scheduler.PushJobEvent(jobEvent)
		}
	}
	//从该revision向后监听变化事件
	go func() {
		//从当前版本开始监听
		watchStartRevision := getResp.Header.Revision + 1
		//启动监听
		watchRespChan := j.watcher.Watch(context.TODO(), common.JOB_SAVE_DIR, clientv3.WithRev(watchStartRevision), clientv3.WithPrefix())
		//处理监听事件
		for watchResponse := range watchRespChan {
			for _, event := range watchResponse.Events {
				switch event.Type {
				case mvccpb.PUT:
					job, err := common.UnpackJob(event.Kv.Value)
					if err != nil {
						continue
					}
					//构建一个更新event事件
					jobEvent := common.BuildJobEvent(common.JOB_EVENT_SAVE, job)
					//推送一个更新事件给scheduler
					G_scheduler.PushJobEvent(jobEvent)
				case mvccpb.DELETE:
					jobName := common.ExtractJobName(string(event.Kv.Key), common.JOB_SAVE_DIR)
					//构建一个删除event事件
					jobEvent := common.BuildJobEvent(common.JOB_EVENT_DELETE, &common.Job{Name: jobName})
					//推送一个删除事件给scheduler
					G_scheduler.PushJobEvent(jobEvent)
				}
			}
		}
	}()

	return nil
}

//创建分布式锁
func (j *JobMgr) CreateJobLock(jobName string) (jobLock *JobLock) {
	return InitJobLock(jobName, j.kv, j.lease)
}

//监听强杀任务
func (j *JobMgr) watchKiller() (err error) {
	go func() {
		//启动监听
		watchRespChan := j.watcher.Watch(context.TODO(), common.JOB_KILLER_DIR, clientv3.WithPrefix())
		//处理监听事件
		if watchResponse, ok := <-watchRespChan; ok {
			for _, event := range watchResponse.Events {
				switch event.Type {
				case mvccpb.PUT: //监听到put操作
					jobName := common.ExtractJobName(string(event.Kv.Key), common.JOB_KILLER_DIR)
					//构建一个删除event事件
					jobEvent := common.BuildJobEvent(common.JOB_EVENT_KILLER, &common.Job{Name: jobName})
					//推送一个删除事件给scheduler
					G_scheduler.PushJobEvent(jobEvent)
				case mvccpb.DELETE: //监听到DELETE操作，不做处理

				}
			}
		}
	}()

	return
}
